#ifndef COROUTINE_TIMERMANAGER_H
#define COROUTINE_TIMERMANAGER_H

#include <cstdint>
#include <functional>
#include <memory>
#include <shared_mutex>
#include <set>
namespace DBServer {
namespace coroutine {

/// @brief 定时器的管理类
class TimerManager;

/// @brief 定时器
class Timer : public std::enable_shared_from_this<Timer> {
    friend class TimerManager;
public:
    using ptr = std::shared_ptr<Timer>;

    /// @brief 取消定时器
    bool cancel();

    /// @brief 刷新设置定时器的执行时间 
    bool refresh();

    /// @brief 重置定时器时间
    /// @param ms_ 定时器执行时间间隔
    /// @param from_now 是否从当前时间开始计算
    bool reset(std::uint64_t ms_, bool from_now);

private:
    Timer(std::uint64_t ms_, std::function<void()> cb_, bool recurring_, TimerManager *manager);

    Timer(std::uint64_t next);

private:
    bool recurring = false;                 // 是否循环执行定时器
    std::uint64_t ms = 0;                   // 执行周期
    std::uint64_t next = 0;                 // 下一次的执行时间
    std::function<void()> cb;               // 回调函数
    TimerManager *manager = nullptr;        // 定时器管理器

private:
    struct Comparator {
        /// @brief 比较定时器执行时间的仿函数
        bool operator()(const Timer::ptr &lhs, const Timer::ptr &rhs) const;
    };
};

class TimerManager {
    friend class Timer;
public:
    TimerManager() = default;

    virtual ~TimerManager() = default;

    /// @brief 添加定时器
    Timer::ptr add_timer(std::uint64_t ms, std::function<void()> cb, bool recurring = false);

    /// @brief 添加条件定时器
    /// @param weak_cond 条件
    Timer::ptr add_condition_timer(std::uint64_t ms, std::function<void()> cb, std::weak_ptr<void> weak_cond, bool recurring = false);

    /// @brief 到最近一个定时器执行的时间间隔(毫秒)
    std::uint64_t get_next_time();

    /// @brief 获取需要执行的定时器的回调函数列表
    /// @param[out] cbs 回调函数数组
    void list_expire_cb(std::vector<std::function<void()>>& cbs);

    /// @brief 时间堆是否为空
    bool empty();

protected:
    /// @brief 当有新的定时器插入到时间堆的首部是，执行该函数
    virtual void on_timer_insert_at_front() {}

    /// @brief 将定时器添加到管理器中
    void add_timer(Timer::ptr val, std::shared_mutex &mtx);

private:
    std::shared_mutex rb_mtx;                               // 读写锁
    std::set<Timer::ptr, Timer::Comparator> timer_heap;     // 时间堆
    bool tickled = false;                                   // 是否触发
    std::uint64_t prev_time = 0;                            // 上次执行时间
};

}   // coroutine   
}   // DBServer


#endif // !COROUTINE_TIMERMANAGER_H